package com.caltco.cargo.ops.modules.sys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.caltco.cargo.ops.auth.bo.AdminUserDetails;
import com.caltco.cargo.ops.common.exception.RRException;
import com.caltco.cargo.ops.modules.sys.dao.FrequencyStatisticsDao;
import com.caltco.cargo.ops.modules.sys.dao.LearnBookDao;
import com.caltco.cargo.ops.modules.sys.dao.WordDao;
import com.caltco.cargo.ops.modules.sys.entity.FrequencyStatistics;
import com.caltco.cargo.ops.modules.sys.entity.LearnBook;
import com.caltco.cargo.ops.modules.sys.entity.LearnWord;
import com.caltco.cargo.ops.modules.sys.entity.List.Meaning;
import com.caltco.cargo.ops.modules.sys.entity.Word;
import com.caltco.cargo.ops.modules.sys.request.SaveLearnBookRequest;
import com.caltco.cargo.ops.modules.sys.service.WordService;
import com.caltco.cargo.ops.modules.sys.vo.LearnBookVO;
import com.caltco.cargo.ops.modules.sys.vo.WordVO;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Service
public class WordServiceImp implements WordService {
    // 艾宾浩斯遗忘曲线的间隔天数
    private static final List<Integer> INTERVALS = Arrays.asList(1, 2, 4, 8, 16);
    private final WordDao wordDao;
    private final LearnBookDao learnBookDao;
    private final FrequencyStatisticsDao frequencyStatisticsDao;
    private final ObjectMapper objectMapper = new ObjectMapper();

    public WordServiceImp(WordDao wordDao, LearnBookDao learnBookDao, FrequencyStatisticsDao frequencyStatisticsDao) {
        this.wordDao = wordDao;
        this.learnBookDao = learnBookDao;
        this.frequencyStatisticsDao = frequencyStatisticsDao;
    }

    public Long getUserIdByToken() {
        return ((AdminUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUserEntity().getUserId();
    }

    @Override
    public WordVO getWordByType(String type) {
        Long userId = getUserIdByToken();
        WordVO wordVO = wordDao.getWordByType(userId, type);
        List<String> jsonStrings = wordDao.getRandomErrorWords();
        List<List<Meaning>> result = new ArrayList<>();
        for (String jsonStr : jsonStrings) {
            try {
                // 将每个字符串解析为 List<WordDefinition>
                List<Meaning> list = objectMapper.readValue(
                        jsonStr, new TypeReference<List<Meaning>>() {
                        });
                result.add(list);
            } catch (JsonProcessingException e) {
                throw new RuntimeException("解析失败", e);
            }
        }
        wordVO.setErrorWord(result);
        return wordVO;
    }

    @Override
    public WordVO getByRandom() {
        return getWordByEnter();
    }

    private WordVO getWordsToReview() {
        WordVO wordVO = wordDao.getWordsToReview(getUserIdByToken());
        List<String> jsonStrings = wordDao.getRandomErrorWords();
        List<List<Meaning>> result = new ArrayList<>();
        for (String jsonStr : jsonStrings) {
            try {
                // 将每个字符串解析为 List<WordDefinition>
                List<Meaning> list = objectMapper.readValue(
                        jsonStr, new TypeReference<List<Meaning>>() {
                        });
                result.add(list);
            } catch (JsonProcessingException e) {
                throw new RuntimeException("解析失败", e);
            }
        }
        wordVO.setErrorWord(result);
        return wordVO;
    }

    @Override
    public void updateReviewStatus(Long wordId, Integer isCurrent, String wordType) {
        FrequencyStatistics frequencyStatistics = frequencyStatisticsDao.selectOne(new MPJLambdaWrapper<FrequencyStatistics>()
                .eq(FrequencyStatistics::getWordId, wordId)
                .eq(FrequencyStatistics::getUserId, getUserIdByToken()));
        if (frequencyStatistics == null) {
            frequencyStatistics = new FrequencyStatistics();
            frequencyStatistics.setWordType(wordType);
            frequencyStatistics.setUserId(getUserIdByToken());
            frequencyStatistics.setWordId(wordId);
            if (isCurrent == 0) {
                frequencyStatistics.setCorrectCount(1);
                frequencyStatistics.setIsReview(1);
            } else {
                frequencyStatistics.setIncorrectCount(1);
                int interval = INTERVALS.get(Math.min(frequencyStatistics.getIncorrectCount(), INTERVALS.size() - 1));
                frequencyStatistics.setReviewDate(LocalDateTime.now());
                frequencyStatistics.setNextReviewDate(LocalDateTime.now().plusDays(interval));
            }
            frequencyStatisticsDao.insert(frequencyStatistics);
        } else {
            if (isCurrent == 0) {
                frequencyStatistics.setCorrectCount(frequencyStatistics.getCorrectCount() + 1);
                frequencyStatistics.setIsReview(1);
            } else {
                if (frequencyStatistics != null) {
                    frequencyStatistics.setIncorrectCount(frequencyStatistics.getIncorrectCount() + 1);
                    // 计算下一次复习的间隔
                    int interval = INTERVALS.get(Math.min(frequencyStatistics.getIncorrectCount(), INTERVALS.size() - 1));
                    frequencyStatistics.setReviewDate(LocalDateTime.now());
                    frequencyStatistics.setNextReviewDate(LocalDateTime.now().plusDays(interval));
                }
            }
            frequencyStatisticsDao.updateById(frequencyStatistics);
        }

    }

    @Override
    public WordVO getWordByTest() {
        return getWordsToReview();
    }

    @Override
    public WordVO getWordByEnter() {
        WordVO wordVO = wordDao.getByRandom();
        List<String> jsonStrings = wordDao.getRandomErrorWords();
        List<List<Meaning>> result = new ArrayList<>();
        for (String jsonStr : jsonStrings) {
            try {
                // 将每个字符串解析为 List<WordDefinition>
                List<Meaning> list = objectMapper.readValue(
                        jsonStr, new TypeReference<List<Meaning>>() {
                        });
                result.add(list);
            } catch (JsonProcessingException e) {
                throw new RuntimeException("解析失败", e);
            }
        }
        wordVO.setErrorWord(result);
        return wordVO;
    }

    @Override
    public List<LearnBookVO>
    getLearnBook() {
        List<LearnBookVO> learnBookVOS = learnBookDao.selectJoinList(LearnBookVO.class,
                new MPJLambdaWrapper<LearnBook>()
                        .selectAll(LearnBook.class)
                        .selectAs("COUNT(DISTINCT w.id)", LearnBookVO::getWordTotal)
                        .selectAs("COUNT(DISTINCT fs.id)", LearnBookVO::getLearnedWord)
                        .leftJoin(FrequencyStatistics.class, "fs", FrequencyStatistics::getWordType, LearnBook::getBookType)
                        .leftJoin(Word.class, "w", Word::getWordType, LearnBook::getBookType)
                        .eq(LearnBook::getUserId, getUserIdByToken())
                        .groupBy(LearnBook::getId, LearnBook::getUserId, LearnBook::getBookType, LearnBook::getIsDelete) // 添加 GROUP BY
        );
        return learnBookVOS;
    }

    @Override
    public List<LearnBookVO> getAllLearnBook() {
        List<LearnBookVO> learnBookVOS = wordDao.selectJoinList(LearnBookVO.class,
                new MPJLambdaWrapper<Word>()
                        .selectAs(Word::getWordType, LearnBook::getBookType)
                        .selectAs("COUNT(*)", LearnBookVO::getWordTotal)
                        .groupBy(Word::getWordType)
        );
        return learnBookVOS;
    }

    @Override
    public Boolean removeLearnBook(SaveLearnBookRequest request) {
        learnBookDao.delete(new LambdaQueryWrapper<LearnBook>()
                .eq(LearnBook::getBookType, request.getType())
                .eq(LearnBook::getUserId, getUserIdByToken())
        );
        return true;
    }

    @Override
    public Boolean saveLearnBook(SaveLearnBookRequest request) {
        LearnBook learnBook = learnBookDao.selectOne(new LambdaQueryWrapper<LearnBook>()
                .eq(LearnBook::getBookType, request.getType())
                .eq(LearnBook::getUserId, getUserIdByToken()));
        if (learnBook != null) {
            throw new RRException("您已添加该书");
        }
        learnBook = new LearnBook();
        learnBook.setBookType(request.getType());
        learnBook.setUserId(getUserIdByToken());
        learnBookDao.insert(learnBook);
        return true;
    }
}
